using System;
using System.Collections.Generic;
using System.Text;
using NUnit.Framework;
using moDb_prototype;
using System.IO;
using moDb_tests.Stubs;
using NMock2;
using System.Data;
using System.Data.SqlClient;
using System.Collections;


namespace moDb_tests
{
    [TestFixture]
    public class With_ManangedRecordOfT_Test
    {
        private Person instance;
        private ManagedRecord<Person> personRecord;
        private Mockery mocks;
        private IDbCommand mockCommand;

        #region ExpectedResults & Inputs
        private const string expectedResult = "ID = 1|Age = 26|Name = Michael|DateOfBirth = 1981/01/18 12:00:00 AM";
        private const string parseInput = "ID = 1|Age = 26|Name = Michael|DateOfBirth = 1981/01/18"; 
        #endregion

        [SetUp]
        public void Setup()
        {
            //mocks = new Mockery();
            //Database.Connection = mocks.NewMock<IDbConnection>();
            //mockCommand = mocks.NewMock<IDbCommand>();
            instance = new Person();
            instance.Name = "Michael";
            instance.Age = 26;
            instance.DateOfBirth = new DateTime(1981, 1, 18);             
            //Expect.AtLeastOnce
            //    .On(Database.Connection)
            //    .Method("CreateCommand")                
            //    .Will(Return.Value(mockCommand));
            personRecord = new ManagedRecord<Person>(instance);
        }
        [Test]
        public void Serialization()
        {   
            Stream stream = new MemoryStream();
            BinaryWriter writer = new BinaryWriter(stream);            
            personRecord.Write(writer);            
            BinaryReader reader = new BinaryReader(stream);
            resetStream(stream);
            personRecord.Read(reader);
            Assert.AreEqual(personRecord.Instance.Name, "Michael");
            Assert.AreEqual(personRecord.Instance.Age, 26);
            Assert.AreEqual(personRecord.Instance.DateOfBirth, new DateTime(1981,1,18));
            Assert.AreSame(personRecord.Instance, instance);
            instance = personRecord.Instance; //For any Tests that want to follow this one
        }        
        [Test]
        public new void ToString()
        {            
            Assert.AreEqual(expectedResult, personRecord.ToString());
        }
        [Test]
        public void ToStringAfterSerialization()
        {
            Serialization();
            ToString();
        }
        [Test]
        public void Parse()
        {
            Assert.AreEqual(expectedResult,
                ManagedRecord<Person>.Parse(parseInput).ToString());
        }

        [Test]
        public void Save()
        {
            IDataParameterCollection parameters = mocks.NewMock<IDataParameterCollection>();

            Expect.Once
                .On(mockCommand)
                .GetProperty("Parameters")
                .Will(Return.Value(parameters));

            Expect.Once
                .On(parameters)
                .Method("Add")
                .With(Has.Property("Value",Is.EqualTo(instance)))
                .Will(Return.Value(0));

            Expect.Once
                .On(Database.Connection)
                .Method("Open");

            Expect.Once
                .On(mockCommand)
                .Method("ExecuteNonQuery")
                .Will(Return.Value(1));

            Expect.Once
                .On(Database.Connection)
                .Method("Close");             

            personRecord.Save();            
        }

        [Test]
        [Category("ActualDatabaseTest")]
        public void SaveToActualDatabase()
        {
            //mocks.Dispose(); //Not using mocks here my friend :)
            Database.ConnectionString = "Data Source=Mistress;Initial Catalog=moDb;Integrated Security=True";            
            personRecord.Save();
        }

        private static void resetStream(Stream stream)
        {
            ((MemoryStream)stream).Position = 0;
        }
    }
}
